package br.ufrj.ppgi.infovis.forms;

import org.mt4j.components.TransformSpace;
import org.mt4j.components.visibleComponents.widgets.MTTextArea;
import org.mt4j.components.visibleComponents.widgets.MTTextField;
import org.mt4j.util.font.IFont;
import org.mt4j.util.font.IFontCharacter;

import processing.core.PApplet;

/**
 * <p>
 * This MTTextFieldVarLinesFontSwitch allows a variable number of lines of text
 * (up to TEXT_FIELD_VAR_MAX_LINES) and adds a line break after each line has
 * reached the width of the TextField. In addition to that, it switched to a
 * smaller font when the width of the first line is reached.
 * </p>
 * @see MTTextArea
 * @see MTTextField
 * @see MTTextFieldVarLines
 * 
 */
public class MTTextFieldVarLinesFontSwitch extends MTTextFieldVarLines {
    /* *** Text field variable lines with font switch constants *** */
    /** The text field width offset */
    protected static final int TEXT_FIELD_WIDTH_OFFSET = 10;

    /* *** Fonts *** */
    /** The default (bigger) font */
    private IFont              defaultFont;
    /** The smaller font */
    private IFont              smallerFont;
    /** Flag that indicates that fontSwitch should not be performed */
    private boolean            lockSwitchFont          = false;

    /* ***********Constructors*********** */
    /**
     * Constructor. Instantiates a new MTTTextFieldTwoLines.
     * 
     * @param applet
     *            the application instance
     * @param x
     *            the x position of the var line text field
     * @param y
     *            the y position of the var line text field
     * @param width
     *            the width of the var line text field
     * @param height
     *            the height of the var line text field
     * @param maxNumberOfLines
     *            the maximum number of lines in the variable TextField
     * @param fontDefault
     *            the default font
     * @param fontSmall
     *            the smaller font that we switch to once we reached the width
     *            of the text field in the first line
     */
    public MTTextFieldVarLinesFontSwitch(PApplet applet, float x, float y,
            float width, float height, int maxNumberOfLines, IFont fontDefault,
            IFont fontSmall) {
        super(applet, x, y, width, height, maxNumberOfLines, fontDefault);
        // Set font references
        this.defaultFont = fontDefault;
        this.smallerFont = fontSmall;
    }

    /* ********Overridden methods******** */
    /**
     * Method called after a character is added to the
     * MTTextFieldVarLinesFontSwitch (e.g. via a keyboard). Checks which line we
     * are in (max. lines is maxNumberOfLines), begins a new line if necessary,
     * removes added character if we have reached the maxNumberOfLines limit and
     * switches the font if we have reached the character limit for one single
     * line.
     * 
     * @param character
     *            the added character
     * @see org.mt4j.components.visibleComponents.widgets.MTTextArea#characterAdded
     *      (org.mt4j.components.visibleComponents.font.IFontCharacter)
     */
    @Override
    protected void characterAdded(IFontCharacter character) {
        // Special handling of line breaks
        if (character.getUnicode().equalsIgnoreCase("\n")) { //$NON-NLS-1$
            float localWidth = this.getWidthXY(TransformSpace.LOCAL);
            localWidth += TEXT_FIELD_WIDTH_OFFSET;
            // We are now in the second line (getLineCount() == 1))
            if (getLineCount() < this.getMaxNumberOfLines()) {
                // switch to smaller font
                if (!this.lockSwitchFont && !this.isClearActive()
                        && this.getText().length() > 0
                        && this.getFont().equals(this.defaultFont)) {
                    this.setFont(this.smallerFont);
                }
            } else { // we are in "no more lines allowed" land, remove \n
                this.removeLastCharacter();
            }

        } else {
            // If we are still in the first line (getLineCount()==0)
            if (getLineCount() < (this.getMaxNumberOfLines() - 1)) {
                // If the end of the line is reached, switch to smaller font or
                // start a new line with the new character if small font is
                // already
                // set
                float localWidth = this.getWidthXY(TransformSpace.LOCAL);
                localWidth += TEXT_FIELD_WIDTH_OFFSET;

                // We still have less than the maximum number of lines and the
                // default font, so
                // switch
                // the font
                if (!this.lockSwitchFont && !this.isClearActive()
                        && this.getText().length() > 0
                        && getLastCharEndPos() > localWidth
                        && this.getFont().equals(this.defaultFont)) {
                    this.setFont(this.smallerFont);
                }
                // We still have less than the maximum number of lines and the
                // small font is
                // already
                // set, so we start a new line
                if (!this.isClearActive() && this.getText().length() > 0
                        && getLastCharEndPos() > localWidth
                        && this.getFont().equals(this.smallerFont)) {
                    // Start new line and add character there
                    this.appendCharByUnicode("\n"); //$NON-NLS-1$
                    this.appendCharByUnicode(character.getUnicode());
                    this.lockSwitchFont = false;
                }
            } else { // We are in line maxNumberOfLines (or more, which should
                     // not be the case)
                float localWidth = this.getWidthXY(TransformSpace.LOCAL);
                localWidth += TEXT_FIELD_WIDTH_OFFSET;

                // If the end of the line is reached, don't add any characters
                if (this.getText().length() > 0
                        && getLastCharEndPos() > localWidth) {
                    // No more chars are to be added
                    this.removeLastCharacter();
                }
            }
        }
    }

    /**
     * Method called after a character has been removed from the
     * MTTextFieldVarLinesFontSwitch (e.g. via a keyboard). Switches the font if
     * we have reached the character limit for one line.
     * 
     * @param character
     *            the removed character
     * @see org.mt4j.components.visibleComponents.widgets.MTTextArea#characterRemoved
     *      (org.mt4j.components.visibleComponents.font.IFontCharacter)
     * 
     */
    @Override
    protected void characterRemoved(IFontCharacter character) {
        // If we just removed character over the local width border,
        // and we are in line one with clear() not active switch to the default
        // font
        float localWidth = this.getWidthXY(TransformSpace.LOCAL);
        localWidth += TEXT_FIELD_WIDTH_OFFSET;
        if (!this.lockSwitchFont && !this.isClearActive() && getLineCount() < 1
                && this.getFont().equals(this.smallerFont)
                && getLastCharEndPos() <= localWidth) {
            this.setFont(this.defaultFont);
        }
    }
}
